package com.giscloud.token.filter;

import com.alibaba.fastjson.JSON;
import com.giscloud.commons.utils.JacksonUtil;
import com.giscloud.commons.utils.ResultUtil;
import com.giscloud.commons.utils.StringUtils;
import com.giscloud.commons.utils.TokenUtil;
import com.giscloud.token.cache.LocalCacheManager;
import com.giscloud.token.utils.RedisConstant;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.util.ObjectUtils;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Set;

/**
 * @Author:gxd
 * @Description:
 * @Date: 23:50 2019/8/21
 * @Modified By:
 */
@Configuration
@Log4j2
@ConditionalOnExpression("'${spring.cache.type}'!='redis'")
public class TokenFilter implements Filter {
    @Value("${giscloud.allowUrl: *}")
    private String allowUrl;
    @Value("${giscloud.allowPaths:/amp/login,/amp/logout,/amp/validateCode}")
    private Set<String> allowPaths;
    //签名秘钥,可以换成 秘钥 注入
    @Value("${giscloud.jwt.secret:eed3c844dc9247aa9959581081f7495e}")
    private String secret;
    @Autowired
    private LocalCacheManager localCacheManager;
    public static final String  ACCESS_TOKEN = "giscloud-token";


    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;
        //前端react项目的域名
        response.setHeader("Access-Control-Allow-Origin", allowUrl);
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT");
        response.setHeader("Access-Control-Max-Age", "36000");
        //设置允许访问cookie
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept,Authorization,giscloud-token");
        String path = request.getRequestURI().substring(request.getContextPath().length()).replaceAll("[/]+$", "");
        boolean allowedPath = allowPaths.contains(path);
        if(path.contains("/file/fetch") || path.contains("/file/download") || path.contains("/static/dynamicsql")){
            allowedPath = true;
        }
        /****************************本地开发用,上线注掉************************/
//        if(true){
//            chain.doFilter(request, response);
//            return;
//        }
        String staffId = "",tokenStr = "";
        if (HttpMethod.OPTIONS.name().equalsIgnoreCase(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
        }else {
            if (!allowedPath) {
                tokenStr = request.getHeader(ACCESS_TOKEN);
                if (StringUtils.isBlank(tokenStr)) {
                    tokenStr = request.getParameter(ACCESS_TOKEN);
                }
                if(StringUtils.isBlank(tokenStr)){
                    returnJson(response, JacksonUtil.bean2Json(ResultUtil.error(-2, "token信息为空，请重新登录")));
                    return;
                }
                // 从本地缓存中获取用户信息
                String tokenObj = localCacheManager.get(RedisConstant.REDIS_USER_TOKEN + tokenStr);
                if(ObjectUtils.isEmpty(tokenObj)){
                    returnJson(response, JacksonUtil.bean2Json(ResultUtil.error(-2, "token已经过期，请重新登录")));
                    return;
                }
                //token = JacksonUtil.json2Bean(tokenObj.toString(), Token.class);
                Claims claims = null;
                try {
                    claims = TokenUtil.parseJWT(tokenStr, secret);
                    staffId = claims.getId();
                } catch (ExpiredJwtException e) {
                    log.error("token已经过期,请重新登录,{}",e);
                    returnJson(response, JacksonUtil.bean2Json(ResultUtil.error(-2, "token已经过期，请重新登录")));
                    return;
                } catch (Exception e) {
                    log.error("token错误,请重新登录,{}",e);
                    returnJson(response, JacksonUtil.bean2Json(ResultUtil.error(-2, "token错误,请重新登录")));
                    return;
                }
            }
            //运行通过
            if (allowedPath) {
                chain.doFilter(request, response);
            }else{
                returnJson(response, JSON.toJSONString(ResultUtil.error(-2,"token已经过期，请重新登录")));
                return;
            }
        }
    }
    private void returnJson(HttpServletResponse response, String json){
        PrintWriter writer = null;
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        try {
            writer = response.getWriter();
            writer.print(json);
        } catch (IOException e) {
            log.error("response error,{}",e);
        } finally {
            if (writer != null) {
                writer.close();
            }
        }
    }
    @Override
    public void destroy() {

    }
}